package common

import (
	"crypto/sha1"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io"
	"os"
	"path"
	"reflect"
	"runtime"
	"strconv"
	"strings"
	"time"

	"github.com/valyala/fasthttp"
)

const (
	SUCCESS byte = 0
	WARNING byte = 1
	ERROR   byte = 2
)

type Response *map[string]interface{}

func DateTime(t time.Time) string {
	return t.Format("2006-01-02 15:04:05")
}

func SendSmile(data interface{}, args ...interface{}) Response {
	result := make(map[string]interface{})
	for _, arg := range args {
		switch arg.(type) {
		case string:
			result["msg"] = arg
		case byte:
			result["code"] = arg
		}
	}

	result["data"] = data
	if _, ok := result["msg"]; !ok {
		result["msg"] = "获取数据成功"
	}
	if _, ok := result["code"]; !ok {
		result["code"] = SUCCESS
	}

	return &result
}

func SendSad(msg string, args ...interface{}) Response {
	result := make(map[string]interface{})
	for _, arg := range args {
		_, ok := arg.(byte)
		if ok {
			result["code"] = arg
		} else {
			result["data"] = arg
		}
	}
	result["msg"] = msg
	if _, ok := result["data"]; !ok {
		result["data"] = nil
	}
	if _, ok := result["code"]; !ok {
		result["code"] = WARNING
	}
	return &result
}

func SendCry(msg string, args ...interface{}) Response {
	result := make(map[string]interface{})
	for _, arg := range args {
		_, ok := arg.(byte)
		if ok {
			result["code"] = arg
		} else {
			result["data"] = arg
		}
	}
	result["msg"] = msg
	if _, ok := result["data"]; !ok {
		result["data"] = nil
	}
	if _, ok := result["code"]; !ok {
		result["code"] = ERROR
	}
	return &result
}

// 解析唯一账号至appid与账号
func ParseAccount(account string) (uint, string) {
	s := strings.Split(account, "_")
	if len(s) != 2 {
		return 0, ""
	}
	appid, err := strconv.Atoi(s[0])
	if err != nil {
		return 0, ""
	}

	return uint(appid), s[1]
}

func SmartPrint(i interface{}) {
	var kv = make(map[string]interface{})
	vValue := reflect.ValueOf(i)
	vType := reflect.TypeOf(i)
	for i := 0; i < vValue.NumField(); i++ {
		kv[vType.Field(i).Name] = vValue.Field(i)
	}
	fmt.Println("获取到数据:")
	for k, v := range kv {
		fmt.Print(k)
		fmt.Print(":")
		fmt.Print(v)
		fmt.Println()
	}
}

func PathExists(path string) (bool, error) {
	_, err := os.Stat(path)
	if err == nil {
		return true, nil
	}
	if os.IsNotExist(err) {
		return false, nil
	}
	return false, err
}

func HttpDo(method string, urlStr string, jsonData interface{}, headers *map[string]string) ([]byte, error) {
	var (
		req         = fasthttp.AcquireRequest()
		resp        = fasthttp.AcquireResponse()
		result      = []byte("")
		requestStrs []string
		requestStr  string
		requestByte []byte

		interval string

		err error
	)

	defer fasthttp.ReleaseRequest(req)
	defer fasthttp.ReleaseResponse(resp)

	// 默认是application/x-www-form-urlencoded
	req.Header.SetContentType("application/json")
	req.Header.SetMethod(strings.ToUpper(method))
	if headers != nil {
		for k, v := range *headers {
			req.Header.Set(k, v)
		}
	}

	if jsonData != nil {
		if method == "GET" {
			r := reflect.ValueOf(jsonData).MapRange()
			for {
				if !r.Next() {
					break
				}
				requestStrs = append(requestStrs, r.Key().String()+"="+fmt.Sprint(r.Value().Interface()))
			}
			requestStr = strings.Join(requestStrs, "&")

			if strings.Contains(urlStr, "?") {
				interval = "&"
			} else {
				interval = "?"
			}
			urlStr += interval + requestStr
			fmt.Println(urlStr)
		} else {
			requestByte, _ = json.Marshal(jsonData)
			req.SetBody(requestByte)
		}
	}

	req.SetRequestURI(urlStr)

	if err = fasthttp.Do(req, resp); err != nil {
		return result, err
	}

	result = resp.Body()
	return result, nil
}

func StringToInt64(s string) int64 {
	i, _ := strconv.ParseInt(strings.TrimSpace(s), 10, 64)
	return i
}
func StringSliceToIntSlice(ss []string)[]int64{
	var list = []int64{}
	for _,s := range ss{
		list = append(list, StringToInt64(s))
	}
	return list
}
func ToInterfaceSlice(in interface{}) []interface{} {
	var out []interface{}
	switch in.(type) {
	case []string:
		for _, v := range in.([]string) {
			out = append(out, v)
		}
	case []int64:
		for _, v := range in.([]int64) {
			out = append(out, v)
		}
	}
	return out
}
func Sha1(data string, length int) string {
	sha1 := sha1.New()
	sha1.Write([]byte(data))
	res := hex.EncodeToString(sha1.Sum([]byte("")))
	if length <= 0 || len(res) <= length {
		return res
	}
	return res[:length]
}
func Sha1FromReader(src io.Reader) string {
	h := sha1.New()
	_, _ = io.Copy(h, src)
	return hex.EncodeToString(h.Sum(nil))
}
func IsNil(i interface{}) bool {
	if i==nil{
		return true
	}
	defer func() {
		recover()
	}()
	vi := reflect.ValueOf(i)
	return vi.IsNil()
}
func TransferFloat(s string) float64 {
	f, _ := strconv.ParseFloat(s, 64)
	return f
}
func GetEventPath() string {
	_, filename, _, _ := runtime.Caller(0)
	var cwdPath string
	cwdPath = path.Join(path.Dir(filename), "") // the the main function file directory
	paths := strings.Split(cwdPath, "/")
	return strings.Join(paths[:len(paths)-1], "/")
}